﻿using InTheHand.Bluetooth;
using InTheHand.Net.Sockets;

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UCTT.NetFx.BTComm
{
    public partial class BluetoothForm : Form
    {
        #region    字段 start
        private readonly string gp_BTDevicesRawTitle;
        private readonly string gp_BLEDevicesRawTitle;

        private BluetoothService btWrap;
        private bool isSearching;// 是否搜索中
        private List<(string, int, string)> BTDeviceList = new List<(string, int, string)>();// 缓存上一次的经典蓝牙设备信息
        #endregion 字段 end

        #region    构造与析构 start
        public BluetoothForm()
        {
            InitializeComponent();
            this.dgv_BluetoothDevices.AutoGenerateColumns = false;
            //this.dgv_BluetoothDevices.DataSource = this.BTDeviceList;
            this.dgv_BluetoothLEDevices.AutoGenerateColumns = false;

            gp_BTDevicesRawTitle = gp_BTDevices.Text;
            gp_BLEDevicesRawTitle = gp_BLEDevices.Text;

            btWrap = new BluetoothService();
            btWrap.RadioStateChanged += BtWrap_RadioStateChanged;
            btWrap.BTConnected += BtWrap_BTConnected;
            btWrap.Received += BtWrap_Received;
            btWrap.UpdateBTDevcice += BtWrap_UpdateBTDevcice;
            btWrap.UpdateBLEDevcice += BtWrap_UpdateBLEDevcice;

            btWrap.PrintEnumsAndConstCollection();
        }
        #endregion 构造与析构 end

        #region    事件处理 start
        // 窗体加载事件
        private void BluetoothForm_Load(object sender, EventArgs e)
        {
            UpdateRadioInfo();
            btn_Search.Enabled = btWrap.IsRadioReady;
            btn_Connect.Enabled = btWrap.IsRadioReady;
        }

        // 窗体关闭前事件
        private void BluetoothForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isSearching)
            {
                btWrap.StopScanLE();
            }
            btWrap.UpdateBTDevcice -= BtWrap_UpdateBTDevcice;
            btWrap.UpdateBLEDevcice -= BtWrap_UpdateBLEDevcice;
        }

        // DataGridView所有单元格绘制之后的事件 => 隐藏三角箭头并重绘行号(对齐属性无效)
        private void dgv_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            var dgv = sender as DataGridView;
            Color color = Color.Black; //dgv.RowHeadersDefaultCellStyle.ForeColor;
            using (SolidBrush b = new SolidBrush(color))
            {
                e.Graphics.DrawString((e.RowIndex + 1).ToString(), e.InheritedRowStyle.Font, b, e.RowBounds.Location.X, e.RowBounds.Location.Y + 3);// 重绘行号
            }
            dgv.RowHeadersDefaultCellStyle.Padding = new Padding(dgv.RowHeadersWidth);// 去掉行头三角号
        }

        // DataGridView鼠标单击事件 => 单击空白处时取消选中行
        private void dgv_MouseClick(object sender, MouseEventArgs e)
        {
            var dgv = sender as DataGridView;
            if (GetRowIndexAt(dgv, e.Y) == -1)
            {
                dgv.ClearSelection();
            }
        }

        // DataGridView双击行事件 => 连接选中行的设备
        private async void dgv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            var dgv = sender as DataGridView;
            var flag = false;
            if (dgv == dgv_BluetoothDevices)
            {
                flag = ConnectDevice(true);
            }
            else if (dgv == dgv_BluetoothLEDevices)
            {
                flag = await ConnectLEDevice(true);
            }
            if (flag)
            {
                btn_Connect.Text = "断开";
            }
        }

        // 蓝牙适配器状态改变事件
        private void BtWrap_RadioStateChanged(bool isReady)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<bool>(BtWrap_RadioStateChanged), isReady);
            }
            else
            {
                UpdateRadioInfo();
                btn_Search.Enabled = isReady;
                btn_Connect.Enabled = isReady;
            }
        }

        private void BtWrap_Received(BluetoothDeviceInfo e, Socket client, NetworkStream stream)
        {
            while (true)
            {
                var dataLen = client.Available;
                if (dataLen > 0)
                {
                    byte[] buffer = new byte[dataLen];
                    stream.Read(buffer, 0, dataLen);

                    var hexStr = BitConverter.ToString(buffer, 0, dataLen);
                    PrintLog(hexStr);
                }
            }
            //if (stream == null)
            //{
            //    return;
            //}
            //while (stream.CanRead && stream.DataAvailable)
            //{
            //    while (stream.ReadByte() > -1)
            //    {

            //    }
            //    //using (StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8))
            //    //{
            //    //    string line = string.Empty;
            //    //    //while (!string.IsNullOrWhiteSpace(line = sr.ReadLine()))
            //    //    while (!sr.EndOfStream)
            //    //    {
            //    //        line = line.TrimStart('\0');
            //    //        Trace.WriteLine(line);
            //    //        PrintLog(line);

            //    //        var binData = Encoding.UTF8.GetBytes(line);
            //    //        var hexStr = BitConverter.ToString(binData, 0, binData.Length);
            //    //        PrintLog(line);
            //    //    }
            //    //}


            //    //while (true)
            //    //{
            //    //    byte[] buffer = new byte[10];
            //    //    int bytesRead = stream.Read(buffer, 0, buffer.Length);
            //    //    var hexStr = BitConverter.ToString(buffer, 0, buffer.Length);
            //    //    PrintLog(hexStr);

            //    //    using (var ms = new MemoryStream(buffer))
            //    //    {
            //    //        var img = Image.FromStream(stream);
            //    //        建立一个IDataObject对象存储图片
            //    //        IDataObject dataObj = new DataObject();
            //    //        //调用SetData方法储存图片
            //    //        dataObj.SetData(img);
            //    //        //将图片复制到剪贴板上
            //    //        Clipboard.SetDataObject(dataObj, false);
            //    //        rtb_Log.SelectionStart = rtb_Log.Text.Length;
            //    //        //将剪贴板中的内容贴入RichTextBox中
            //    //        rtb_Log.Paste();
            //    //        rtb_Log.AppendText(Environment.NewLine + "测试结束！");
            //    //    }
            //    //}
            //}
        }

        // 经典蓝牙设备连接成功时
        private void BtWrap_BTConnected(IAsyncResult ar)
        {
            if (ar.IsCompleted)
            {

            }
        }

        // Bt设备列表更新事件
        private void BtWrap_UpdateBTDevcice(List<(string, int, bool)> infoList, List<BluetoothDeviceInfo> deviceInfoLst)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<List<(string, int, bool)>, List<BluetoothDeviceInfo>>(BtWrap_UpdateBTDevcice), infoList, deviceInfoLst);
            }
            else
            {
                UpdateBTDevices(infoList, deviceInfoLst);
            }
        }

        // Ble设备列表更新事件
        private void BtWrap_UpdateBLEDevcice(BluetoothAdvertisingEvent e, (string, short, bool) newItem)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<BluetoothAdvertisingEvent, (string, short, bool)>(BtWrap_UpdateBLEDevcice), e, newItem);
            }
            else
            {
                UpdateBLEDevices(e, newItem);
            }
        }

        private void BluetoothForm_Resize(object sender, EventArgs e)
        {
            gp_BTDevices.Width = tlp_Content.Width / 2 - gp_BTDevices.Left;
            gp_BLEDevices.Width = tlp_Content.Width / 2 - gp_Operation.Width;
        }

        // 开始/停止搜索蓝牙设备
        private void btn_Search_Click(object sender, EventArgs e)
        {
            btn_Search.Enabled = false;
            try
            {
                if (btn_Search.Text == "搜索")
                {
                    isSearching = true;
                    //dgv_BluetoothDevices.Rows.Clear();
                    gp_BTDevices.Text = gp_BTDevicesRawTitle;
                    dgv_BluetoothLEDevices.Rows.Clear();
                    gp_BLEDevices.Text = gp_BLEDevicesRawTitle;

                    SearchDevice(isSearching);
                    btn_Search.Text = "停止";
                }
                else if (btn_Search.Text == "停止")
                {
                    isSearching = false;
                    SearchDevice(isSearching);
                    //btWrap.StopScanLE();
                    btn_Search.Text = "搜索";
                }
            }
            catch// (Exception ex)
            {

            }
            finally
            {
                btn_Search.Enabled = true;
            }
        }

        // 连接/断开蓝牙设备
        private void btn_Connect_Click(object sender, EventArgs e)
        {
            btn_Connect.Enabled = false;
            gp_BTDevices.Enabled = false;
            gp_BLEDevices.Enabled = false;
            try
            {
                var flag = false;
                if (btn_Connect.Text == "连接")
                {
                    flag = ConnectDevice(true);
                    if (flag)
                    {
                        btn_Connect.Text = "断开";
                    }
                }
                else if (btn_Connect.Text == "断开")
                {
                    flag = ConnectDevice(false);
                    if (flag)
                    {
                        btn_Connect.Text = "连接";
                    }
                }
            }
            catch// (Exception ex)
            {

            }
            finally
            {
                gp_BTDevices.Enabled = true;
                gp_BLEDevices.Enabled = true;
                btn_Connect.Enabled = true;
            }
        }

        private void btn_SendLeft_Click(object sender, EventArgs e)
        {
            //btWrap.WriteRegister
        }

        private void btn_ClearLeft_Click(object sender, EventArgs e)
        {

        }
        #endregion 事件处理 end

        #region    私有方法 start
        /// <summary>
        /// 蓝牙适配器状态变更
        /// </summary>
        /// <param name="isReady"></param>
        private void RadioStateChanged(bool isReady)
        {
            lbl_RadioState.Text = isReady ? "蓝牙已打开" : "蓝牙未打开";
            lbl_RadioState.ForeColor = isReady ? Color.Green : Color.Red;
            if (isReady)
            {
                tt_tip.Hide(lbl_RadioState);
            }
            else
            {
                var tip = string.IsNullOrWhiteSpace(lbl_RadioName.Text) && string.IsNullOrWhiteSpace(lbl_RadioMac.Text) ? "请检查蓝牙适配器是否存在或驱动是否安装，如果适配器正常请打开系统蓝牙开关" : "请打开系统蓝牙开关";
                tt_tip.SetToolTip(lbl_RadioState, tip);
                //tt_tip.Active = true;
                tt_tip.ToolTipIcon = ToolTipIcon.Warning;
                tt_tip.Show(tip, lbl_RadioState);
            }
        }

        /// <summary>
        /// 更新蓝牙适配器信息
        /// </summary>
        private void UpdateRadioInfo()
        {
            RadioStateChanged(btWrap.IsRadioReady);
            if (btWrap.IsRadioReady)
            {
                lbl_RadioName.Text = btWrap.PrimaryRadio.Name.Trim();
                lbl_RadioMac.Text = btWrap.PrimaryRadio.LocalAddress.ToStringSplitByColon(true);
            }
        }

        /// <summary>
        /// 开始/停止搜索设备
        /// </summary>
        /// <param name="isSearch"></param>
        private void SearchDevice(bool isSearch)
        {
            if (isSearch)
            {
                Task.Factory.StartNew(() =>
                    {
                        Parallel.Invoke(
                        () =>
                        {
                            btWrap.StartScan();
                        },
                        async () =>
                        {
                            await btWrap.StartScanLEAsync();
                        });
                    });
            }
            else
            {
                btWrap.StopScan();
                btWrap.StopScanLE();
            }
        }

        /// <summary>
        /// 连接/断开BT设备
        /// </summary>
        /// <param name="isConnect">true表示连接/false表示断开</param>
        private bool ConnectDevice(bool isConnect)
        {
            bool isCompleted = false;
            //IAsyncResult result = null;
            BluetoothDeviceInfo bdi = null;
            var dgvr_BT = dgv_BluetoothDevices.SelectedRows.Count > 0 ? dgv_BluetoothDevices.SelectedRows[0] : null;
            if (dgvr_BT != null)
            {
                if (isConnect)
                {
                    bdi = dgvr_BT.Tag as BluetoothDeviceInfo;
                    if (bdi != null)
                    {
                        isCompleted = btWrap.Connect(bdi);
                        if (isCompleted)
                        {
                            dgvr_BT.HeaderCell.Style.BackColor = Color.SkyBlue;
                        }
                    }
                }
                else
                {
                    isCompleted = btWrap.Disconnect();
                    if (isCompleted)
                    {
                        dgvr_BT.HeaderCell.Style.BackColor = SystemColors.Control;
                    }
                }
            }
            return isCompleted;
        }

        /// <summary>
        /// 连接/断开连接BLE设备
        /// </summary>
        /// <param name="isConnect">true表示连接/false表示断开</param>
        private async Task<bool> ConnectLEDevice(bool isConnect)
        {
            bool isCompleted = false;
            BluetoothDevice bd = null;
            var dgvr_BLE = dgv_BluetoothLEDevices.SelectedRows.Count > 0 ? dgv_BluetoothLEDevices.SelectedRows[0] : null;
            if (dgvr_BLE != null)
            {
                bd = dgvr_BLE.Tag as BluetoothDevice;
                if (isConnect)
                {
                    if (bd != null)
                    {
                        var uuid = BluetoothUuid.FromId("6863bcaf-6544-4e47-6961-68676e616853");
                        isCompleted = await btWrap.ConnectLEAsync(bd, uuid);
                        if (isCompleted)
                        {
                            dgvr_BLE.HeaderCell.Style.BackColor = Color.SkyBlue;
                        }
                    }
                }
                else
                {
                    await btWrap.DisconnectLE();
                    isCompleted = true;
                    dgvr_BLE.HeaderCell.Style.BackColor = SystemColors.Control;
                }
            }
            return isCompleted;
        }

        /// <summary>
        /// 更新BT设备列表
        /// </summary>
        private void UpdateBTDevices(List<(string, int, bool)> infoList, List<BluetoothDeviceInfo> deviceInfoLst)
        {
            var isFrist = dgv_BluetoothDevices.Rows.Count == 0;
            deviceInfoLst.ForEach(bdi =>
            {
                var devName = string.IsNullOrWhiteSpace(bdi.DeviceName) ? "Unknown" : bdi.DeviceName;
                var devStr = $"{bdi.DeviceAddress}({devName})";
                var isConnected = bdi.Connected ? "是" : "否";
                (bool isExists, int rowIndex) = ExistsInDGV(dgv_BluetoothDevices, devStr);
                if (isExists)
                {
                    var dgvr = dgv_BluetoothDevices.Rows[rowIndex];
                    dgvr.Cells["Col_BTIsConnected"].Value = isConnected;
                    dgvr.Tag = bdi;
                }
                else
                {
                    var index = dgv_BluetoothDevices.Rows.Add(devStr, isConnected, "...");
                    var dgvr = dgv_BluetoothDevices.Rows[index];
                    dgvr.Tag = bdi;
                }
                gp_BTDevices.Text = $"{gp_BTDevicesRawTitle}({dgv_BluetoothDevices.Rows.Count})";
            });
            if (isFrist)
            {
                dgv_BluetoothDevices.ClearSelection();
            }
        }

        /// <summary>
        /// 更新BLE设备列表
        /// </summary>
        private void UpdateBLEDevices(BluetoothAdvertisingEvent e, (string, short, bool) newItem)
        {
            var isFrist = dgv_BluetoothLEDevices.Rows.Count == 0;
            (bool isExists, int rowIndex) = ExistsInDGV(dgv_BluetoothLEDevices, newItem.Item1);
            if (isExists)
            {
                var dgvr = dgv_BluetoothLEDevices.Rows[rowIndex];
                dgvr.Cells["Col_BLERssi"].Value = newItem.Item2;
            }
            else
            {
                var index = dgv_BluetoothLEDevices.Rows.Add(newItem.Item1, newItem.Item2, newItem.Item3 ? "是" : "否", "...");
                var dgvr = dgv_BluetoothLEDevices.Rows[index];
                dgvr.HeaderCell.Value = $"{index + 1}";
                dgvr.Tag = e.Device;
                gp_BLEDevices.Text = $"{gp_BLEDevicesRawTitle}({dgv_BluetoothLEDevices.Rows.Count})";
            }
            if (isFrist)
            {
                dgv_BluetoothLEDevices.ClearSelection();
            }
        }

        /// <summary>
        /// 判断指定的bt/ble设备是否已存在与列表中
        /// </summary>
        /// <param name="dgv">设备列表</param>
        /// <param name="devStr">指定的ble设备字符串"mac(name)"</param>
        /// <returns></returns>
        private (bool, int) ExistsInDGV(DataGridView dgv, string devStr)
        {
            (bool isExists, int rowIndex) = (false, -1);
            foreach (DataGridViewRow dgvr in dgv.Rows)
            {
                var firstCellValue = dgvr.Cells[0].Value.ToString();
                var addr = devStr.Substring(0, 12);
                if (firstCellValue.StartsWith(addr))
                {
                    isExists = true;
                    rowIndex = dgvr.Index;
                }
            }
            return (isExists, rowIndex);
        }

        /* 调试追踪*/
        private void DebugTrack(RichTextBox log, string str, Color color)
        {
            if (log.InvokeRequired)
            {
                Action<RichTextBox, string, Color> method = this.DebugTrack;
                log.Invoke(method, str, color);
            }
            else
            {
                /* 字符串的长度超过1000 自动清空接收显示界面 */
                if (log.TextLength > 1000)
                {
                    log.Clear(); // 清空
                }

                log.SelectionStart = log.Text.Length;
                log.SelectionColor = color;  // 选择打印的颜色

                /* 在接收数据前面显示时间 可选可不选 */
                if (true)//(checkBoxShowTime.Checked) // 如果显示时间被选中 
                {
                    /* 在打印出来的信息的前面追加时间字符串 */
                    log.AppendText(DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss] ") + str);
                }
                else
                {
                    //log.AppendText(str); // 不添加时间 直接在后面追加字符串
                    // this.log.AppendText("aaa"+"\r\n"); // 不添加时间 直接在后面追加字符串 
                }

                log.ScrollToCaret();  // 将控件内容滚动到当前插入符号位置 不加，光标在最初的位置，加上后，光标滚动到插入位置的最后面
            }
        }

        private void PrintLog(string str)
        {
            PrintLog(str, Color.Black);
        }

        /* 打印字符串 */
        private void PrintLog(string str, Color color)
        {
            if (rtb_LogLeft.InvokeRequired)
            {
                rtb_LogLeft.Invoke(new Action<string, Color>(PrintLog), str, color);
            }
            else
            {
                //if (rtb_Log.TextLength > 4000)
                //{
                //    rtb_Log.Clear(); // 清空
                //}

                //DebugTrack(richTextBoxState, str, color);  // 打印出这个字符串 黑色显示
                rtb_LogLeft.SelectionStart = rtb_SendLeft.Text.Length;
                rtb_LogLeft.SelectionColor = color;  // 选择打印的颜色
                rtb_LogLeft.AppendText(DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss.fff] ") + str + "\r\n");
                rtb_LogLeft.ScrollToCaret();  // 将控件内容滚动到当前插入符号位置 不加，光标在最初的位置，加上后，光标滚动到插入位置的最后面
            }
        }


        /// <summary>
        /// 判断鼠标单击的位置是否在DataGridViewRow上
        /// </summary>
        /// <param name="dgv"></param>
        /// <param name="mouseLocation_Y"></param>
        /// <returns></returns>

        private int GetRowIndexAt(DataGridView dgv, int mouseLocation_Y)
        {
            if (dgv.FirstDisplayedScrollingRowIndex < 0)
            {
                return -1;
            }

            if (dgv.ColumnHeadersVisible == true && mouseLocation_Y <= dgv.ColumnHeadersHeight)
            {
                return -1;
            }

            int index = dgv.FirstDisplayedScrollingRowIndex;
            int displayedCount = dgv.DisplayedRowCount(true);

            for (int k = 1; k <= displayedCount; k++)
            {
                if (dgv.Rows[index].Visible)
                {
                    var rect = dgv.GetRowDisplayRectangle(index, true);  // 取该区域的显示部分区域
                    if (rect.Top <= mouseLocation_Y && mouseLocation_Y < rect.Bottom)
                    {
                        return index;
                    }
                    //k++;
                }
                index++;
            }
            return -1;
        }

        #endregion 私有方法 end
    }
}